


#ifndef __PHYSICSWORLD_H__
#define __PHYSICSWORLD_H__

#include <Box2D/Box2D.h>
#include "GLES-Render.h"

class PhysicsWorld;

typedef PhysicsWorld* TestCreateFcn();

struct Settings
{
    Settings() :
        viewCenter(0.0f, 20.0f),
        hz(60.0f),
        velocityIterations(8),
        positionIterations(3),
        drawShapes(1),
        drawJoints(1),
        drawAABBs(0),
        drawPairs(0),
        drawContactPoints(0),
        drawContactNormals(0),
        drawContactForces(0),
        drawFrictionForces(0),
        drawCOMs(0),
        drawStats(0),
        drawProfile(0),
        enableWarmStarting(1),
        enableContinuous(1),
        enableSubStepping(0),
        pause(0),
        singleStep(0)
        {}

    b2Vec2 viewCenter;
    float32 hz;
    int32 velocityIterations;
    int32 positionIterations;
    int32 drawShapes;
    int32 drawJoints;
    int32 drawAABBs;
    int32 drawPairs;
    int32 drawContactPoints;
    int32 drawContactNormals;
    int32 drawContactForces;
    int32 drawFrictionForces;
    int32 drawCOMs;
    int32 drawStats;
    int32 drawProfile;
    int32 enableWarmStarting;
    int32 enableContinuous;
    int32 enableSubStepping;
    int32 pause;
    int32 singleStep;
};


const int32 k_maxContactPoints = 2048;

struct ContactPoint
{
    b2Fixture* fixtureA;
    b2Fixture* fixtureB;
    b2Vec2 normal;
    b2Vec2 position;
    b2PointState state;
};


struct TestEntry
{
    const char *name;
    TestCreateFcn *createFcn;
};

extern TestEntry g_testEntries[];
// This is called when a joint in the world is implicitly destroyed
// because an attached body is destroyed. This gives us a chance to
// nullify the mouse joint.
class DestructionListener : public b2DestructionListener
{
public:
    void SayGoodbye(b2Fixture* fixture) { B2_NOT_USED(fixture); }
    void SayGoodbye(b2Joint* joint);

    PhysicsWorld* test;
};

class PhysicsWorld : public b2ContactListener
{
public:

    PhysicsWorld();
    virtual ~PhysicsWorld();

    void			SetTextLine(int32 line) { m_textLine = line; }
    virtual void	Step(Settings* settings);
    virtual void	Keyboard(unsigned char key) { B2_NOT_USED(key); }
    virtual void	KeyboardUp(unsigned char key) { B2_NOT_USED(key); }
    void			ShiftMouseDown(const b2Vec2& p);
    virtual bool	MouseDown(const b2Vec2& p);
    virtual void	MouseUp(const b2Vec2& p);
    void			MouseMove(const b2Vec2& p);

    // Let derived tests know that a joint was destroyed.
    virtual void	JointDestroyed(b2Joint* joint) { B2_NOT_USED(joint); }

    // Callbacks for derived classes.
    virtual void	BeginContact(b2Contact* contact) { B2_NOT_USED(contact); }
    virtual void	EndContact(b2Contact* contact) { B2_NOT_USED(contact); }
    virtual void	PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
    virtual void	PostSolve(const b2Contact* contact, const b2ContactImpulse* impulse)
    {
        B2_NOT_USED(contact);
        B2_NOT_USED(impulse);
    }

public:

    b2Body* m_groundBody;
    b2AABB m_worldAABB;
    int32 m_pointCount;
    ContactPoint m_points[k_maxContactPoints];
    DestructionListener m_destructionListener;
    GLESDebugDraw* m_debugDraw;
    int32 m_textLine;
    b2World* m_world;
    b2Body* m_bomb;
    b2MouseJoint* m_mouseJoint;
    b2Vec2 m_bombSpawnPoint;
    bool m_bombSpawning;
    b2Vec2 m_mouseWorld;
    int32 m_stepCount;

    b2Profile m_maxProfile;
    b2Profile m_totalProfile;
};



#endif